package legumes.client.ui.basket.grids;

import java.util.List;
import java.util.Map;

import legumes.client.evt.customer.CustomerOrderChangedEvent;
import legumes.client.evt.manager.EventBusManager;
import legumes.shared.domain.OnSaleProduct;
import legumes.shared.domain.OrderPart;
import legumes.shared.domain.OrderPartProductItem;
import legumes.shared.domain.Quantity;
import legumes.shared.domain.SellSessionForCustomer;
import legumes.shared.domain.Unit;

import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.NumberFormat;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.types.ListGridFieldType;
import com.smartgwt.client.types.SelectionAppearance;
import com.smartgwt.client.widgets.form.fields.ComboBoxItem;
import com.smartgwt.client.widgets.form.fields.FormItem;
import com.smartgwt.client.widgets.form.fields.TextItem;
import com.smartgwt.client.widgets.grid.CellFormatter;
import com.smartgwt.client.widgets.grid.HeaderSpan;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.grid.ListGridSummaryField;
import com.smartgwt.client.widgets.grid.RecordSummaryFunction;
import com.smartgwt.client.widgets.grid.events.EditCompleteEvent;
import com.smartgwt.client.widgets.grid.events.EditCompleteHandler;
import com.smartgwt.client.widgets.grid.events.EditorEnterEvent;
import com.smartgwt.client.widgets.grid.events.EditorEnterHandler;
import com.smartgwt.client.widgets.grid.events.SelectionChangedHandler;
import com.smartgwt.client.widgets.grid.events.SelectionEvent;
import com.smartgwt.client.widgets.layout.VLayout;

public class BasketOutsidePanel extends VLayout {

	private ListGrid listGrid;
	private ListGridField userQuantityUnitField;
	private ListGridField userQuantityField;
	private SellSessionForCustomer sellSessionForCustomer;
	private OrderPart op;
	
	public BasketOutsidePanel() {
		super();
		setWidth100();
		setHeight("50%");
		
		setShowEdges(true);
		setMembersMargin(5);  
        setLayoutMargin(10); 
        
		build();
	}
	
	public void initData(SellSessionForCustomer sellSessionForCustomer_, OrderPart op_){
		op = op_;
		sellSessionForCustomer = sellSessionForCustomer_;
		displaySellSessionForCustomer();
	}
	
	protected void displaySellSessionForCustomer() {
    	
		List<OnSaleProduct> onSaleProducts = sellSessionForCustomer.getStall().getOnSaleProducts();
		int i=0;
		ListGridRecord [] records = new ListGridRecord[onSaleProducts.size()];
		for (OnSaleProduct p : onSaleProducts) {
			try{
				ListGridRecord record = new ListGridRecord();
				record.setAttribute("isSelected", true);
				record.setAttribute("prix", p.getPrice().getAmount() );
				record.setAttribute("libelle", p.getProduct().getName() );
				record.setAttribute("quantite", p.getPrice().getQuantity().getValue() );
				record.setAttribute("unit", p.getPrice().getQuantity().getUnit() );
//				if(p!= null && p.getProduct() != null && p.getProduct().getProductType() != null ){
//					record.setAttribute("categorie", p.getProduct().getProductType() );
//					
//				} else {
//					record.setAttribute("categorie", "L");
//				}
				records[i]= record;
				i++;
			} catch (NullPointerException e_) {
				GWT.log("Err on displaySellSessionForCustomer ", e_);
			}
		}
		listGrid.setRecords(records);
	}
	
	private void build(){
		listGrid = new ListGrid();
        
        ListGridField categoryField = new ListGridField("categorie");  
        categoryField.setCanEdit(false);
        categoryField.setHidden(true);
        
        ListGridField libelleField = new ListGridField("libelle", "Produit", 100);  
        libelleField.setCanEdit(false);
        
        userQuantityField = new ListGridField("userQuantite", "Quantit&eacute;", 50);
        userQuantityField.setAlign(Alignment.RIGHT);
        userQuantityField.setType(ListGridFieldType.FLOAT);
        
        userQuantityUnitField = new ListGridField("userQuantiteUnit", "Unit&eacute; quantit&eacute;", 150);
        userQuantityUnitField.setAlign(Alignment.RIGHT);
        //TODO set value MAP
        //The value map depends of the current record
        
        ListGridField priceField = new ListGridField("prix", "Prix", 150); 
        priceField.setCanEdit(false);
        priceField.setAlign(Alignment.RIGHT);  
        priceField.setCellFormatter(new CellFormatter() {  
            public String format(Object value_, ListGridRecord record_, int rowNum, int colNum) {  
            	if(value_ == null) return null;  
                NumberFormat nf = NumberFormat.getFormat("0.00");
                String valueStr = value_.toString();
                try {  
                    valueStr = nf.format(((Number) value_).floatValue());
                    valueStr += " &#8364;";
                } catch (Exception e) {  
                    return "";  
                }  
                String unit = record_.getAttribute("unit");
                float quantite = record_.getAttributeAsFloat("quantite");
                
                if(unit != null){
                    unit = unit.toUpperCase();
                } else {
                    unit = "";
                }
                return valueStr == null ? "" : 
                	quantite == 1 ?
                			valueStr + " &frasl; " + unit :
                			valueStr + " &frasl; " + quantite + " " + unit ;
                
            }  
        });
  
        ListGridSummaryField totalField = new ListGridSummaryField("total", "Total", 50);  
        totalField.setCanEdit(false);
        totalField.setAlign(Alignment.RIGHT);          
        totalField.setRecordSummaryFunction(new RecordSummaryFunction(){

            @Override
            public Object getSummaryValue(Record record_, ListGridField[] fields_, ListGridField summaryField_) {
                float total = 0.0f;
                try{
                    if( record_.getAttributeAsBoolean("isSelected")){
                    	float coef = 1.0f;
                    	String unit = record_.getAttribute("unit");
                    	if(unit.equalsIgnoreCase(Unit.KG.name()) 
                    			&& record_.getAttribute("userQuantiteUnit").equalsIgnoreCase(Unit.G.name())){
                    		coef = 1/1000f;
                    	} else if (unit.equalsIgnoreCase(Unit.G.name()) 
                    			&& record_.getAttribute("userQuantiteUnit").equalsIgnoreCase(Unit.KG.name())){
                    		coef = 1000f;
                    	}
                    	
                        total = record_.getAttributeAsFloat("prix") 
                        		* record_.getAttributeAsFloat("userQuantite")
                    			* coef
                    			/ record_.getAttributeAsFloat("quantite");
                    } else {
                    	total = 0f;
                    }
                } catch(Exception e_){
                    
                }
                return new Float(total);
            }
            
        });
        
        totalField.setCellFormatter(new CellFormatter() {
            
            public String format(Object value, ListGridRecord record, int rowNum, int colNum) {  
                if (value == null) return null;
                
                try {  
                    NumberFormat nf = NumberFormat.getFormat("#,##0.00");  
                    return nf.format(((Number) value).doubleValue()) + " &#8364;";  
                } catch (Exception e) {  
                    try{
                        float f = Float.parseFloat( value.toString() );  
                        NumberFormat nf = NumberFormat.getFormat("#,##0.00");  
                        return nf.format(f) + " &#8364;";   
                    } catch(Exception e2){
                        return value.toString();  
                    }
                    
                }  
            }  
        });  
         
        listGrid.setSelectOnEdit(true);
        listGrid.setWidth100();  
        listGrid.setHeight("50%");
        listGrid.setHeaderHeight(40); 
        listGrid.setShowAllRecords(true);
        listGrid.setCanEdit(true);  
        listGrid.setGroupByField("categorie");  
        listGrid.setGroupStartOpen("all");
        
        listGrid.setSelectionAppearance(SelectionAppearance.CHECKBOX); 
        
        listGrid.setHeaderSpans(  
                new HeaderSpan("Les l&eacute;gumes au choix", new String[]{"libelle", "prix"}),  
                new HeaderSpan("Votre commande", new String[]{"userQuantite", "userQuantiteUnit", "total"}) );  
  
        listGrid.setFields(categoryField, libelleField, priceField, userQuantityField,  userQuantityUnitField, totalField);  
  
        listGrid.addSelectionChangedHandler(new SelectionChangedHandler(){

            @Override
            public void onSelectionChanged(SelectionEvent event_) {
                Record r = event_.getRecord();
            	float price = r.getAttributeAsFloat("prix");
            	String unit = r.getAttribute("unit");
            	float quantite = r.getAttributeAsFloat("quantite");
            	String productName = r.getAttributeAsString("libelle");
            	float userQuantite = -1;
            	try{
            		userQuantite = r.getAttributeAsFloat("userQuantite");
            	} catch(Exception e_){
            	}
            	
            	String userQuantiteUnit = r.getAttributeAsString("userQuantiteUnit");
            	
            	OrderPartProductItem oppi = op.findOrderPartProductItemFor(productName);
            	if( oppi == null ){
            		oppi = new OrderPartProductItem();
            		OnSaleProduct product = sellSessionForCustomer.getStall().findOnSaleProduct(productName);
                	oppi.setOnSaleProduct(product);
            		op.addOrderPartProductItem(oppi);
            	}
            	//If selected
            	if( event_.getState() ){
            		if(userQuantite == -1){
            			//No quantity has been specified => We set to to default quantity
            			userQuantite = r.getAttributeAsFloat("quantite");
            			r.setAttribute("userQuantite", userQuantite);
            		}
            		if(userQuantiteUnit == null || userQuantiteUnit.length()<=0){
            			//No quantity unit specified => We set to to default quantity unit
            			userQuantiteUnit = r.getAttribute("unit");
            			r.setAttribute("userQuantiteUnit", userQuantiteUnit);
            		}
            		//We update the quantity 
            		
            		Quantity q = new Quantity();
            		q.setUnit(userQuantiteUnit);
            		q.setValue(userQuantite);
            		oppi.setQuantity(q);
            	} else {
            		//We remove it
            		op.getOrderPartProductItems().remove(oppi);
            	}
            	
            	
            	float coef = 1.0f;
            	if(unit.equalsIgnoreCase(Unit.KG.name()) 
            			&& userQuantiteUnit.equalsIgnoreCase(Unit.G.name())){
            		coef = 1/1000f;
            	} else if (unit.equalsIgnoreCase(Unit.G.name()) 
            			&& userQuantiteUnit.equalsIgnoreCase(Unit.KG.name())){
            		coef = 1000f;
            	}
            	
            	float totalRecordPrice = price*userQuantite*coef/quantite;
            	r.setAttribute("total", totalRecordPrice);
            	listGrid.refreshFields();
            	EventBusManager.getInstance().getEventBus().fireEvent(
                			new CustomerOrderChangedEvent(event_.getState() , totalRecordPrice));
            	
            }
            
        });
        
        listGrid.addEditorEnterHandler(new EditorEnterHandler() {
			
			@Override
			public void onEditorEnter(EditorEnterEvent event) {
				FormItem fi = null;
				
				ListGridRecord lgr = listGrid.getRecord(event.getRowNum());
				String quantiteUnit = lgr.getAttribute("unit");
            	if(quantiteUnit != null &&
            		(	quantiteUnit.equalsIgnoreCase(Unit.G.name())
            		|| 	quantiteUnit.equalsIgnoreCase(Unit.KG.name()))
            	){
            		ComboBoxItem cbi = new ComboBoxItem();
                	cbi.setValueMap(Unit.G.name(), Unit.KG.name());
                	cbi.setValue(quantiteUnit);
                	cbi.setDefaultValue(quantiteUnit);
                	fi = cbi;
            	} else {
            		TextItem ti = new TextItem(quantiteUnit);
            		ti.setDisabled(true);
            		fi = ti;
            	}
            	
            	userQuantityUnitField.setEditorType(fi);  
                userQuantityUnitField.setCanEdit(true);
                userQuantityField.setCanEdit(true);
            	listGrid.refreshFields();
			}
		});
        
        listGrid.addEditCompleteHandler(new EditCompleteHandler() {
			private float computeOldTotal(Record r){
				float quantite = r.getAttributeAsFloat("quantite");
				String unit = r.getAttribute("unit");
				float price = r.getAttributeAsFloat("prix");
				
				
				Float userQuantite = r.getAttributeAsFloat("userQuantite");
				if( userQuantite == null ){
					userQuantite = 0f;
				}
				String userUnit = r.getAttribute("userQuantiteUnit");
				if( userUnit == null ){
					userUnit = unit;
				}
				float coef = 1.0f;
            	if(unit.equalsIgnoreCase(Unit.KG.name()) 
            			&& userUnit.equalsIgnoreCase(Unit.G.name())){
            		coef = 1/1000f;
            	} else if (unit.equalsIgnoreCase(Unit.G.name()) 
            			&& userUnit.equalsIgnoreCase(Unit.KG.name())){
            		coef = 1000f;
            	}
            	float total = userQuantite*price*coef / quantite;
            	
            	return total;
			}
			
			
			@Override
			public void onEditComplete(EditCompleteEvent event) {
				//TODO SMA => Should manage event.getOldRecord() to send event for TOTAL CMDE
				//We take the old total
				//We compute the new total with the quantity
				Record oldRecord = event.getOldRecord();
				float oldTotal = computeOldTotal(oldRecord);
				
				float quantite = oldRecord.getAttributeAsFloat("quantite");
				String unit = oldRecord.getAttribute("unit");
				float price = oldRecord.getAttributeAsFloat("prix");
				
				Map<String, Object> newValues = (Map<String, Object>)event.getNewValues();
				
				//UserQuantity or userQuantityUnit should have changed
				if( newValues != null ){
					// ### USER QUANTITY
					Float newUserQuantite = null;
					try{
						newUserQuantite = new Float(newValues.get("userQuantite").toString());
	            	} catch(Exception e_){
	            		
	            	} finally {
	            		if( newUserQuantite == null ){
		            		//Not edited, take the old one
		            		try{
		            			newUserQuantite = oldRecord.getAttributeAsFloat("userQuantite");
		            			if( newUserQuantite == null ){
		            				newUserQuantite = quantite;
		            			}
		            		} catch(Exception e2_){
		            			newUserQuantite = quantite;
		            		}
	            		}
	            	}
	            	
					// ### USER QUANTITY UNIT
	            	String newUserQuantiteUnit = null;
					try{
	            		newUserQuantiteUnit = newValues.get("userQuantiteUnit").toString();
	            	} catch(Exception e_){
	            	} finally{
	            		if(newUserQuantiteUnit==null){
		            		//Not edited, take the old one
		            		try{
		            			newUserQuantiteUnit = oldRecord.getAttribute("userQuantiteUnit");
		            			if(newUserQuantiteUnit==null){
		            				newUserQuantiteUnit = unit;
		            			}
		            		} catch(Exception e2_){
		            			newUserQuantiteUnit = unit;
		            		}
	            		}
	            	}
					
	            	//We convert the user quantity unit to the vendor display unit
	            	float coef = 1.0f;
	            	if(unit.equalsIgnoreCase(Unit.KG.name()) 
	            			&& newUserQuantiteUnit.equalsIgnoreCase(Unit.G.name())){
	            		coef = 1/1000f;
	            	} else if (unit.equalsIgnoreCase(Unit.G.name()) 
	            			&& newUserQuantiteUnit.equalsIgnoreCase(Unit.KG.name())){
	            		coef = 1000f;
	            	} 
	            	
					float newTotal = newUserQuantite*price*coef / quantite;
					float totalDif = newTotal - oldTotal;
					
					EventBusManager.getInstance().getEventBus().fireEvent(
	            			new CustomerOrderChangedEvent(totalDif>0, Math.abs(totalDif) ));
							
				}
			}
		});
        
        setMembers(listGrid);
	}
}
